home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wview.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-28  |  13.9 KB  |  669 lines

  1.  
  2.  
  3. #include "WINGsP.h"
  4.  
  5. #include <X11/Xresource.h>
  6.  
  7.  
  8.  
  9. /* the notifications about views */
  10.  
  11. char *WMViewSizeDidChangeNotification = "WMViewSizeDidChangeNotification";
  12. char *WMViewFocusDidChangeNotification = "WMViewFocusDidChangeNotification";
  13. char *WMViewRealizedNotification = "WMViewRealizedNotification";
  14.  
  15.  
  16. #define EVENT_MASK  \
  17.     KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
  18.     EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
  19.     VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|\
  20.     SubstructureNotifyMask|SubstructureRedirectMask
  21.  
  22.  
  23. static XSetWindowAttributes defAtts= {
  24.     None,                       /* background_pixmap */
  25.     0,                          /* background_pixel */
  26.     CopyFromParent,             /* border_pixmap */
  27.     0,                          /* border_pixel */
  28.     ForgetGravity,              /* bit_gravity */
  29.     ForgetGravity,        /* win_gravity */
  30.     NotUseful,                  /* backing_store */
  31.     (unsigned) ~0,              /* backing_planes */
  32.     0,                          /* backing_pixel */
  33.     False,                      /* save_under */
  34.     EVENT_MASK,               /* event_mask */
  35.     0,                          /* do_not_propagate_mask */
  36.     False,                      /* override_redirect */
  37.     None,            /* colormap */
  38.     None                        /* cursor */
  39. };
  40.  
  41.  
  42.  
  43. static XContext ViewContext=0;           /* context for views */
  44.  
  45.  
  46.  
  47.  
  48. W_View*
  49. W_GetViewForXWindow(Display *display, Window window)
  50. {
  51.     W_View *view;
  52.     
  53.     if (XFindContext(display, window, ViewContext, (XPointer*)&view)==0) {
  54.     return view;
  55.     }
  56.     return NULL;
  57. }
  58.  
  59.  
  60.  
  61. static void
  62. unparentView(W_View *view)
  63. {
  64.     /* remove from parent's children list */
  65.     if (view->parent!=NULL) {
  66.     W_View *ptr;
  67.     
  68.     ptr = view->parent->childrenList;
  69.     if (ptr == view) {
  70.         view->parent->childrenList = view->nextSister;
  71.     } else {
  72.         while (ptr!=NULL) {
  73.         if (ptr->nextSister == view) {
  74.             ptr->nextSister = view->nextSister;
  75.             break;
  76.         } 
  77.         ptr = ptr->nextSister;
  78.         }
  79.     }
  80.     }
  81.     view->parent = NULL;
  82. }
  83.  
  84.  
  85. static void
  86. adoptChildView(W_View *view, W_View *child)
  87. {
  88.     child->nextSister = NULL;
  89.  
  90.     /* add to end of children list of parent */
  91.     if (view->childrenList == NULL) {
  92.     view->childrenList = child;
  93.     } else {
  94.     W_View *ptr;
  95.     
  96.     ptr = view->childrenList;
  97.     while (ptr->nextSister!=NULL) 
  98.         ptr = ptr->nextSister;
  99.     ptr->nextSister = child;
  100.     }
  101.     child->parent = view;
  102. }
  103.  
  104.  
  105. static W_View*
  106. createView(W_Screen *screen, W_View *parent)
  107. {
  108.     W_View *view;
  109.  
  110.     if (ViewContext==0)
  111.     ViewContext = XUniqueContext();
  112.     
  113.     view = wmalloc(sizeof(W_View));
  114.     memset(view, 0, sizeof(W_View));
  115.     
  116.     view->refCount = 1;
  117.     
  118.     view->screen = screen;
  119.  
  120.     if (parent!=NULL) {
  121.     /* attributes are not valid for root window */
  122.     view->attribFlags = CWEventMask|CWBitGravity;
  123.     view->attribs = defAtts;
  124.  
  125.     view->attribFlags |= CWBackPixel|CWColormap|CWBorderPixel;
  126.     view->attribs.background_pixel = W_PIXEL(screen->gray);
  127.     view->attribs.border_pixel = W_PIXEL(screen->black);
  128.     view->attribs.colormap = screen->colormap;
  129.  
  130.     view->backColor = WMRetainColor(screen->gray);
  131.  
  132.     adoptChildView(parent, view);
  133.     }
  134.  
  135.     return view;
  136. }
  137.  
  138.  
  139.  
  140. W_View*
  141. W_CreateView(W_View *parent)
  142. {
  143.     return createView(parent->screen, parent);
  144. }
  145.  
  146.  
  147. W_View*
  148. W_CreateRootView(W_Screen *screen)
  149. {
  150.     W_View *view;
  151.     
  152.     view = createView(screen, NULL);
  153.  
  154.     view->window = screen->rootWin;
  155.     
  156.     view->flags.realized = 1;
  157.     view->flags.mapped = 1;
  158.     view->flags.root = 1;
  159.     
  160.     view->size.width = 
  161.     WidthOfScreen(ScreenOfDisplay(screen->display, screen->screen));
  162.     view->size.height =
  163.     HeightOfScreen(ScreenOfDisplay(screen->display, screen->screen));
  164.  
  165.     return view;
  166. }
  167.  
  168.  
  169. W_View*
  170. W_CreateTopView(W_Screen *screen)
  171. {
  172.     W_View *view;
  173.     
  174.     view = createView(screen, screen->rootView);
  175.     if (!view)
  176.     return NULL;
  177.  
  178.     view->flags.topLevel = 1;
  179.     view->attribs.event_mask |= StructureNotifyMask;
  180.  
  181.     return view;
  182. }
  183.  
  184.  
  185.  
  186. void
  187. W_RealizeView(W_View *view)
  188. {
  189.     Window parentWID;
  190.     Display *dpy = view->screen->display;
  191.     W_View *ptr;
  192.  
  193.     assert(view->size.width > 0);
  194.     assert(view->size.height > 0);
  195.  
  196.     
  197.     if (view->parent && !view->parent->flags.realized) {
  198.     wwarning("trying to realize widget of unrealized parent");
  199.     return;
  200.     }
  201.  
  202.     if (!view->flags.realized) {
  203.     parentWID = view->parent->window;
  204.     view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
  205.                      view->size.width, view->size.height, 0, 
  206.                      view->screen->depth, InputOutput,
  207.                      view->screen->visual, view->attribFlags,
  208.                      &view->attribs);
  209.     
  210.     XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
  211.  
  212.     view->flags.realized = 1;
  213.  
  214.     if (view->flags.mapWhenRealized) {
  215.         W_MapView(view);
  216.         view->flags.mapWhenRealized = 0;
  217.     }
  218.  
  219.     WMPostNotificationName(WMViewRealizedNotification, view, NULL);
  220.     }
  221.     
  222.     /* realize children */
  223.     ptr = view->childrenList;
  224.     while (ptr!=NULL) {
  225.     W_RealizeView(ptr);
  226.  
  227.     ptr = ptr->nextSister;
  228.     }
  229. }
  230.  
  231.  
  232. void
  233. W_ReparentView(W_View *view, W_View *newParent, int x, int y)
  234. {
  235.     Display *dpy = view->screen->display;
  236.     
  237.     assert(!view->flags.topLevel);
  238.  
  239.     unparentView(view);
  240.     adoptChildView(newParent, view);
  241.  
  242.     if (view->flags.realized) {
  243.     if (newParent->flags.realized) {
  244.         XReparentWindow(dpy, view->window, newParent->window, x, y);
  245.     } else {
  246.         wwarning("trying to reparent realized view to unrealized parent");
  247.         return;
  248.     }
  249.     }
  250.   
  251.     view->pos.x = x;
  252.     view->pos.y = y;
  253. }
  254.  
  255.  
  256.  
  257. void
  258. W_MapView(W_View *view)
  259. {
  260.     if (!view->flags.mapped) {
  261.     if (view->flags.realized) {
  262.         XMapRaised(view->screen->display, view->window);
  263.         XFlush(view->screen->display);
  264.         view->flags.mapped = 1;
  265.     } else {
  266.         view->flags.mapWhenRealized = 1;
  267.     }
  268.     }
  269. }
  270.  
  271.  
  272. /*
  273.  * W_MapSubviews-
  274.  *     maps all children of the current view that where already realized.
  275.  */
  276. void
  277. W_MapSubviews(W_View *view)
  278. {
  279.     XMapSubwindows(view->screen->display, view->window);
  280.     XFlush(view->screen->display);
  281.     
  282.     view = view->childrenList;
  283.     while (view) {
  284.     view->flags.mapped = 1;
  285.     view->flags.mapWhenRealized = 0;
  286.     view = view->nextSister;
  287.     }
  288. }
  289.  
  290.  
  291.  
  292. void
  293. W_UnmapSubviews(W_View *view)
  294. {
  295.     XUnmapSubwindows(view->screen->display, view->window);
  296.     XFlush(view->screen->display);
  297.     
  298.     view = view->childrenList;
  299.     while (view) {
  300.     view->flags.mapped = 0;
  301.     view->flags.mapWhenRealized = 0;
  302.     view = view->nextSister;
  303.     }
  304. }
  305.  
  306.  
  307.  
  308. void
  309. W_UnmapView(W_View *view)
  310. {
  311.     view->flags.mapWhenRealized = 0;
  312.     if (!view->flags.mapped)
  313.     return;
  314.   
  315.     XUnmapWindow(view->screen->display, view->window);
  316.     XFlush(view->screen->display);
  317.     
  318.     view->flags.mapped = 0;
  319. }
  320.  
  321.  
  322. W_View*
  323. W_TopLevelOfView(W_View *view)
  324. {
  325.     W_View *toplevel;
  326.     
  327.     for (toplevel=view; !toplevel->flags.topLevel; toplevel=toplevel->parent);
  328.     
  329.     return toplevel;
  330. }
  331.  
  332.  
  333. static void
  334. destroyView(W_View *view)
  335. {
  336.     W_View *ptr;
  337.  
  338.     if (view->flags.alreadyDead)
  339.     return;
  340.     view->flags.alreadyDead = 1;    
  341.  
  342.     /* delete the balloon text for the view, if there's any */
  343.     WMSetBalloonTextForView(NULL, view);
  344.  
  345.     if (view->nextFocusChain)
  346.         view->nextFocusChain->prevFocusChain = view->prevFocusChain;
  347.     if (view->prevFocusChain)
  348.         view->prevFocusChain->nextFocusChain = view->nextFocusChain;
  349.  
  350.     /* Do not leave focus in a inexisting control */
  351.     if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
  352.     W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
  353.     
  354.     if (view->flags.topLevel) {
  355.     W_FocusInfo *info = view->screen->focusInfo;
  356.     /* remove focus information associated to this toplevel */
  357.     
  358.     if (info) {
  359.         if (info->toplevel==view) {
  360.         view->screen->focusInfo = info->next;
  361.         wfree(info);
  362.         } else {
  363.         while (info->next) {
  364.             if (info->next->toplevel == view)
  365.             break;
  366.             info = info->next;
  367.         }
  368.         if (info->next) {
  369.             W_FocusInfo *next = info->next->next;
  370.             wfree(info->next);
  371.             info->next = next;
  372.         } 
  373.         /* else the toplevel did not have any focused subview */
  374.         }
  375.     }
  376.     }
  377.     
  378.     /* destroy children recursively */
  379.     while (view->childrenList!=NULL) {
  380.     ptr = view->childrenList;
  381.     ptr->flags.parentDying = 1;
  382.  
  383.     W_DestroyView(ptr);
  384.  
  385.     if (ptr == view->childrenList) {
  386.         view->childrenList = ptr->nextSister;
  387.         ptr->parent = NULL;
  388.     }
  389.     }
  390.  
  391.     W_CallDestroyHandlers(view);
  392.  
  393.     if (view->flags.realized) {
  394.     XDeleteContext(view->screen->display, view->window, ViewContext);
  395.     
  396.     /* if parent is being destroyed, it will die naturaly */
  397.     if (!view->flags.parentDying || view->flags.topLevel)
  398.         XDestroyWindow(view->screen->display, view->window);
  399.     }
  400.     
  401.     /* remove self from parent's children list */
  402.     unparentView(view);
  403.  
  404.     W_CleanUpEvents(view);
  405.     
  406.     WMUnregisterViewDraggedTypes(view);
  407.     
  408. #if 0    
  409.     if (view->dragSourceProcs)
  410.     wfree(view->dragSourceProcs);
  411.  
  412.     if (view->dragDestinationProcs)
  413.     wfree(view->dragDestinationProcs);
  414. #endif
  415.     wfree(view);
  416. }
  417.  
  418.  
  419.  
  420. void
  421. W_DestroyView(W_View *view)
  422. {
  423.     W_ReleaseView(view);
  424. }
  425.  
  426.  
  427.  
  428. void
  429. W_MoveView(W_View *view, int x, int y)
  430. {
  431.     assert(view->flags.root==0);
  432.  
  433.     if (view->delegate && view->delegate->willMove) {
  434.     (*view->delegate->willMove)(view->delegate, view, &x, &y);
  435.     }
  436.  
  437.     if (view->pos.x == x && view->pos.y == y) 
  438.     return;
  439.  
  440.     if (view->flags.realized) {
  441.     XMoveWindow(view->screen->display, view->window, x, y);
  442.     }
  443.     view->pos.x = x;
  444.     view->pos.y = y;
  445.  
  446.     if (view->delegate && view->delegate->didMove) {
  447.     (*view->delegate->didMove)(view->delegate, view);
  448.     }
  449. }
  450.  
  451.  
  452. void
  453. W_ResizeView(W_View *view, unsigned int width, unsigned int height)
  454. {    
  455.     int shrinked;
  456.  
  457.     if (view->delegate && view->delegate->willResize) {
  458.     (*view->delegate->willResize)(view->delegate, view, &width, &height);
  459.     }
  460.  
  461.     assert(width > 0);
  462.     assert(height > 0);
  463.  
  464.     if (view->size.width == width && view->size.height == height)
  465.     return;
  466.     
  467.     shrinked = width < view->size.width || height < view->size.height;
  468.     
  469.     if (view->flags.realized) {
  470.     XResizeWindow(view->screen->display, view->window, width, height);
  471.     } 
  472.     view->size.width = width;
  473.     view->size.height = height;
  474.  
  475.     if (view->delegate && view->delegate->didResize) {
  476.     (*view->delegate->didResize)(view->delegate, view);
  477.     }
  478.  
  479.     if (view->flags.notifySizeChanged)
  480.     WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
  481. }
  482.  
  483.  
  484. void
  485. W_RedisplayView(W_View *view)
  486. {
  487.     XEvent ev;
  488.     
  489.     if (!view->flags.mapped)
  490.     return;
  491.     
  492.     ev.xexpose.type = Expose;
  493.     ev.xexpose.display = view->screen->display;
  494.     ev.xexpose.window = view->window;
  495.     ev.xexpose.count = 0;
  496.  
  497.     WMHandleEvent(&ev);
  498. }
  499.  
  500.  
  501. void
  502. W_SetViewBackgroundColor(W_View *view, WMColor *color)
  503. {
  504.     if (view->backColor)
  505.     WMReleaseColor(view->backColor);
  506.     view->backColor = WMRetainColor(color);
  507.  
  508.     view->attribFlags |= CWBackPixel;
  509.     view->attribs.background_pixel = color->color.pixel;
  510.     if (view->flags.realized) {
  511.     XSetWindowBackground(view->screen->display, view->window, 
  512.                  color->color.pixel);
  513.     XClearWindow(view->screen->display, view->window);
  514.     }
  515. }
  516.  
  517.  
  518.  
  519. W_View*
  520. W_FocusedViewOfToplevel(W_View *view)
  521. {
  522.     WMScreen *scr = view->screen;
  523.     W_FocusInfo *info;
  524.     
  525.     for (info = scr->focusInfo; info!=NULL; info = info->next)
  526.     if (view == info->toplevel)
  527.         break;
  528.     
  529.     if (!info)
  530.     return NULL;
  531.     
  532.     return info->focused;
  533. }
  534.  
  535.  
  536. void
  537. W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
  538. {
  539.     WMScreen *scr = toplevel->screen;
  540.     XEvent event;
  541.     W_FocusInfo *info;
  542.     
  543.     for (info = scr->focusInfo; info!=NULL; info = info->next)
  544.     if (toplevel == info->toplevel)
  545.         break;
  546.  
  547.     if (!info) {
  548.     info = wmalloc(sizeof(W_FocusInfo));
  549.     info->toplevel = toplevel;
  550.     info->focused = view;
  551.     info->next = scr->focusInfo;
  552.     scr->focusInfo = info;
  553.     } else {
  554.     event.xfocus.mode = NotifyNormal;
  555.     event.xfocus.detail = NotifyDetailNone;
  556.     if (info->focused) {
  557.         /* simulate FocusOut event */
  558.         event.xfocus.type = FocusOut;
  559.         W_DispatchMessage(info->focused, &event);
  560.     }
  561.     info->focused = view;
  562.     }
  563.     if (view) {
  564.     /* simulate FocusIn event */
  565.     event.xfocus.type = FocusIn;
  566.     W_DispatchMessage(view, &event);
  567.     }
  568. }
  569.  
  570.  
  571. void 
  572. W_BroadcastMessage(W_View *targetParent, XEvent *event)
  573. {
  574.     W_View *target;
  575.     
  576.     target = targetParent->childrenList;
  577.     while (target!=NULL) {
  578.     W_DispatchMessage(target, event);
  579.     
  580.     target = target->nextSister;
  581.     }
  582. }
  583.  
  584.  
  585. void 
  586. W_DispatchMessage(W_View *target, XEvent *event)
  587. {
  588.     if (target->window==None)
  589.     return;
  590.     event->xclient.window = target->window;
  591.     event->xclient.display = target->screen->display;
  592.     
  593.     WMHandleEvent(event);
  594.     /*
  595.     XSendEvent(target->screen->display, target->window, False,
  596.            SubstructureNotifyMask, event);
  597.      */
  598. }
  599.  
  600.  
  601.  
  602. WMView*
  603. W_RetainView(WMView *view)
  604. {
  605.     view->refCount++;
  606.     return view;
  607. }
  608.  
  609.  
  610.  
  611. void
  612. W_ReleaseView(WMView *view)
  613. {
  614.     view->refCount--;
  615.     if (view->refCount < 1) {
  616.     destroyView(view);
  617.     }
  618. }
  619.  
  620.  
  621. WMWidget*
  622. WMWidgetOfView(WMView *view)
  623. {
  624.     return view->self;
  625. }
  626.  
  627.  
  628. WMSize 
  629. WMGetViewSize(WMView *view)
  630. {
  631.     return view->size;
  632. }
  633.  
  634. WMPoint 
  635. WMGetViewPosition(WMView *view)
  636. {
  637.     return view->pos;
  638. }
  639.  
  640.  
  641. void
  642. WMSetViewNotifySizeChanges(WMView *view, Bool flag)
  643. {
  644.     view->flags.notifySizeChanged = flag;
  645. }
  646.  
  647. Window
  648. WMViewXID(WMView *view)
  649. {
  650.     return view->window;
  651. }
  652.  
  653.  
  654. WMPoint
  655. WMGetViewScreenPosition(WMView *view)
  656. {
  657.     WMScreen *scr = W_VIEW_SCREEN(view);
  658.     Window foo;
  659.     int x, y;
  660.     
  661.     XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(view),
  662.               scr->rootWin, 0, 0, &x, &y, &foo);
  663.     
  664.     return wmkpoint(x, y);
  665. }
  666.  
  667.             
  668.  
  669.